package com.sourcetrip.algorithm.abs;

import com.sourcetrip.algorithm.inter.CustomedObjectSort;
import com.sourcetrip.my.modle.SimpleSortItem;

import java.text.DecimalFormat;
import java.util.Comparator;

/**
 * @author: ZhouBert
 * @date: 2020/12/28
 * @description:
 */
public abstract class AbstractCustomedObjectSort<E> implements CustomedObjectSort<E> {

	public E[] elements = null;

	//region variable

	/**
	 * 比较器
	 */
	private Comparator<E> comparator;

	/**
	 * 交换次数
	 */
	private int swapCount = 0;

	/**
	 * 比较次数
	 */
	private int compareCount = 0;

	private long time;
	private DecimalFormat fmt = new DecimalFormat("#.00");

	//endregion


	//region	constructor

	public AbstractCustomedObjectSort(E[] elements, Comparator<E> comparator) {
		this.elements = elements;
		this.comparator = comparator;
	}

	public AbstractCustomedObjectSort(E[] elements) {
		this.elements = elements;
	}

	public AbstractCustomedObjectSort() {
	}

	//endregion


	@Override
	public void sort(E[] objectArr) {
		checkArr(objectArr);

		long begin = System.currentTimeMillis();
		sortArr(objectArr);
		time = System.currentTimeMillis() - begin;
	}

	protected abstract void sortArr(E[] objectArr);


	/**
	 * 将稳定性判断移除
	 * @return
	 */
	@Override
	public String toString() {
		String timeStr = "耗时：" + (time / 1000.0) + "s(" + time + "ms)";
		String compareCountStr = "比较：" + numberString(compareCount);
		String swapCountStr = "交换：" + numberString(swapCount);
		//String stableStr = "稳定性：" ;//+ isStable();
		return "【" + getClass().getSimpleName() + "】\n"
		//		+ stableStr + " \t"
				+ timeStr + " \t"
				+ compareCountStr + "\t "
				+ swapCountStr + "\n";
				//+ "------------------------------------------------------------------";

	}



	//region	common methods

	private String numberString(int number) {
		if (number < 10000) return "" + number;

		if (number < 100000000) return fmt.format(number / 10000.0) + "万";
		return fmt.format(number / 100000000.0) + "亿";
	}

	/**
	 * 比较两个元素的大小
	 * 1.优先使用 variable comparator
	 * 2.强制转换 compare
	 *
	 * @param e1
	 * @param e2
	 * @return 比较结果
	 */
	protected int compare(E e1, E e2) {
		compareCount++;
		return comparator == null ? ((Comparable) e1).compareTo(e2) : comparator.compare(e1, e2);
	}

	/**
	 * 交换
	 *
	 * @param index1
	 * @param index2
	 */
	protected void swap(int index1, int index2) {
		swapCount++;
		E temp = elements[index1];
		elements[index1] = elements[index2];
		elements[index2] = temp;
	}

	/**
	 * 用一个例子判断排序是否稳定
	 * 判断排序是否稳定
	 * * 从结果上来看的话，那只能首先找出所有相等的元素
	 * * //1.从排序完成的数组 newArr 中找出 相等的集合，并放入大集合；
	 * * //2.遍历大集合，比较 oldArr 中是否符合
	 * * 好吧，就算实现出来了效率也不高，就用一个例子来表现吧
	 *
	 * @return
	 */
	public boolean isStable() {
//		if (this instanceof RadixSort) return true;
//		if (this instanceof sorts.CountingSort) return true;
//		if (this instanceof ShellSort) return false;
//		if (this instanceof SelectionSort) return false;


		SimpleSortItem[] students = new SimpleSortItem[20];
		for (int i = 0; i < students.length; i++) {
			students[i] = new SimpleSortItem(10, i * 10);
		}
		sort((E[]) students);
		for (int i = 1; i < students.length; i++) {
			int score = students[i].score;
			int prevScore = students[i - 1].score;
			if (score != prevScore + 10) return false;
		}
		return true;
	}


	//endregion
}
